#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：prod_ctrl_service 
@File    ：input_return.py
@IDE     ：PyCharm 
@Author  ：孔令伟
@Date    ：8/23/24 11:12 AM 
"""
from typing import Dict, Union

from mg_app_framework import MesCode

from common.basic_mongo import (get_batch_code_config_collection, get_feeding_config_collection,
                                get_new_batch_code_config_collection)
from prod_ctrl_service.tool.tool import check_basic_param

"""
####### IF024
生产完成-原料登出-未使用完的原料进行登出操作
原料未使用完，需要登出后留存备用，登出数量为剩余可退数量。成功登出后，MES恢复原料的空闲状态。
上位机未上传登出物料批次时，登出所有有余料的投料批次
"""


async def input_return_check(params: Dict[str, str]) -> Dict[str, Union[str, Dict]]:
    """
    原料未使用完，需要登出后留存备用，登出数量为剩余可退数量。成功登出后，MES恢复原料的空闲状态。
    上位机未上传登出物料批次时，登出所有有余料的投料批次
    :param params:{
               "call_id":"JQ00386",  #接口调用方认证ID, string
               "trace_id":"8941d16b-0581-4e68-8940-a651afff4282",  #接口调用ID, string
               "upperpc_code": "UP011",    #上位机编码, string
               "user_code":"Y001",  #员工编码, string
               "equip_code":"ZP001",   #设备编码, string
               "process_code":"2050",   # 工序编码, string, 必输
               "lot_no":"HQ2403190549088054230"   #要登出的原料批次码, string, 非必输, 未上传登出物料批次时，登出所有有余料的投料批次
            }
    :return:{
               "code": "success",   #接口应答状态代码, success：成功; fail：失败, string
               "data": {}",  # 接口返回结果描述, json数组, 本接口不需要返回数据，返回null
               "info": "OK"   #接口返回信息描述, 如果为fail, 则为fail的异常描述信息, string
            }
    """
    error_msg = ""
    # '接口调用方认证ID/接口调用ID/上位机编码/员工编码/设备编码'是每一个接口都有且必填的入参，检查这些参数是否填写
    basic_param_check_result, basic_param_check_message = check_basic_param(params=params)
    if not basic_param_check_result:
        error_msg += basic_param_check_message
    lot_no = params.get("lot_no")
    process_code = params.get("process_code")
    equip_code = params.get("equip_code")
    # 对登出码值的校验
    if lot_no:
        msg = await check_lot_no(lot_no)
        error_msg += msg
    if error_msg:
        result = {
            "code": MesCode.fail,  # 接口应答状态代码, success：成功; fail：失败, string
            "data": {},  # 接口返回结果描述, json数组, 本接口不需要返回数据，返回null
            "info": error_msg,  # 接口返回信息描述, 如果为fail, 则为fail的异常描述信息, string
        }
        return result

    # 对 指定的原料批次码 或  所有余料 进行登出操作
    await material_logout_function(lot_no=lot_no, equip_code=equip_code, process_code=process_code)

    result = {
        "code": MesCode.success,  # 接口应答状态代码, success：成功; fail：失败, string
        "data": {},  # 接口返回结果描述, json数组, 本接口不需要返回数据，返回null
        "info": "OK",  # 接口返回信息描述, 如果为fail, 则为fail的异常描述信息, string
    }
    return result


async def check_lot_no(lot_no: str):
    """
    对登出码值的校验
    :param lot_no:
    :return:
    """
    sub_collection = get_feeding_config_collection()
    query_filter: dict = {"is_feeding": True, "lot_no": lot_no}
    result = await sub_collection.find_one(query_filter)
    if not result:
        info = "传入码值不存在投料记录;"
    else:
        pipeline = [
            {"$match": query_filter},
            {"$group": {"_id": "$lot_no", "total": {"$sum": "$qty"}}}
        ]
        total_count = 0
        async for rec in sub_collection.aggregate(pipeline):
            total_count += rec["total"]
        info = "传入码值投料记录已消耗完毕，不需要卸料;" if total_count <= 0 else ""
    return info


async def material_logout_function(lot_no: Union[str, None], equip_code: str, process_code: str):
    """
    对 指定的原料批次码 或  所有余料 进行登出操作
    :param process_code:
    :param equip_code:
    :param lot_no:
    :return:
    """
    collection = get_batch_code_config_collection()
    collection_similar = get_new_batch_code_config_collection()
    sub_collection = get_feeding_config_collection()
    query_filter_1: dict = {
        "equip_code": equip_code,
        "process_code": process_code,
        "is_feeding": True}
    if lot_no:
        query_filter_1.update({"lot_no": lot_no})
    document_cursor = sub_collection.find(query_filter_1)
    async for rec in document_cursor:
        qr_code, qty = rec["lot_no"], rec["qty"]
        query_filter_2 = {"qr_code": qr_code}
        update_content = {
            "$inc": {"available_num": qty},
            "$set": {"is_feeding": False}
        }
        if qty > 0:
            document_1 = await collection.find_one(query_filter_2)
            if document_1:
                await collection.find_one_and_update(query_filter_2, update_content)
            else:
                document_2 = await collection_similar.find_one(query_filter_2)
                if document_2:
                    await collection_similar.find_one_and_update(query_filter_2, update_content)
    await sub_collection.update_many(query_filter_1, {'$set': {"is_feeding": False}})
